#!/usr/bin/env python3
"""
文本质量检测工具
用于检测 Whisper 转录结果中的异常模式（如循环重复）
"""

import re
import logging
from typing import Dict, Optional

logger = logging.getLogger(__name__)


def detect_repetition_ratio(text: str, min_length: int = 2, max_length: int = 10) -> float:
    """
    检测文本中的重复字符串比例

    Args:
        text: 待检测文本
        min_length: 最小重复单元长度
        max_length: 最大重复单元长度

    Returns:
        重复字符的比例 (0.0-1.0)
    """
    if not text or len(text) < 10:
        return 0.0

    max_repeat_ratio = 0.0

    # 检测不同长度的重复模式
    for length in range(min_length, max_length + 1):
        # 查找连续重复的模式
        pattern = r'(.{' + str(length) + r'})\1{3,}'  # 至少重复4次
        matches = re.finditer(pattern, text)

        total_repeat_chars = 0
        for match in matches:
            # 计算重复部分的总字符数
            repeated_text = match.group(0)
            total_repeat_chars += len(repeated_text)

        repeat_ratio = total_repeat_chars / len(text)
        max_repeat_ratio = max(max_repeat_ratio, repeat_ratio)

    return max_repeat_ratio


def check_text_quality(text: str) -> Dict:
    """
    检查文本质量，识别 Whisper 幻觉问题

    Args:
        text: 转录文本

    Returns:
        质量检测结果字典:
        {
            'is_valid': bool,           # 是否有效
            'reason': str,              # 失败原因
            'repeat_ratio': float,      # 重复比例
            'has_hallucination': bool,  # 是否存在幻觉
        }
    """
    result = {
        'is_valid': True,
        'reason': None,
        'repeat_ratio': 0.0,
        'has_hallucination': False,
    }

    if not text or not text.strip():
        result['is_valid'] = False
        result['reason'] = '文本为空'
        return result

    # 检测重复比例
    repeat_ratio = detect_repetition_ratio(text)
    result['repeat_ratio'] = repeat_ratio

    # 阈值：超过 20% 的文本是重复的，认为是异常
    if repeat_ratio > 0.2:
        result['is_valid'] = False
        result['has_hallucination'] = True
        result['reason'] = f'检测到异常重复 ({repeat_ratio:.1%})'
        logger.warning(f"文本质量异常: 重复比例 {repeat_ratio:.1%}")
        return result

    # 检测换行分隔的重复行（Whisper 常见幻觉）
    lines = text.split('\n')
    if len(lines) > 5:
        # 统计重复行
        line_counts = {}
        for line in lines:
            line = line.strip()
            if len(line) > 2:  # 忽略过短的行
                line_counts[line] = line_counts.get(line, 0) + 1

        # 找出最多重复的行
        if line_counts:
            max_repeat_count = max(line_counts.values())
            total_lines = len([l for l in lines if len(l.strip()) > 2])

            # 如果某一行重复超过30%，认为是异常
            if max_repeat_count > 5 and max_repeat_count / total_lines > 0.3:
                result['is_valid'] = False
                result['has_hallucination'] = True
                result['reason'] = f'检测到重复行 ({max_repeat_count}次，占{max_repeat_count/total_lines:.1%})'
                logger.warning(f"文本质量异常: 重复行 {max_repeat_count}次")
                return result

    # 检测常见的幻觉模式
    hallucination_patterns = [
        (r'(.)\1{20,}', '单字符重复超过20次'),  # 单个字符重复
        (r'(谢谢观看|谢谢大家|感谢观看){5,}', '结束语重复'),
        (r'(字幕|翻译|制作){10,}', '字幕标记重复'),
    ]

    for pattern, desc in hallucination_patterns:
        if re.search(pattern, text):
            result['is_valid'] = False
            result['has_hallucination'] = True
            result['reason'] = f'检测到{desc}'
            logger.warning(f"文本质量异常: {desc}")
            return result

    # 检测文本长度异常（可能是转录失败）
    if len(text) < 5:
        result['is_valid'] = False
        result['reason'] = '文本过短 (<5字符)'
        return result

    return result


def truncate_repeated_text(text: str, max_repeat: int = 3) -> str:
    """
    截断重复文本，保留前几次重复

    Args:
        text: 原始文本
        max_repeat: 最多保留的重复次数

    Returns:
        处理后的文本
    """
    if not text:
        return text

    # 尝试检测并截断重复模式
    for length in range(10, 2, -1):  # 从长到短
        pattern = r'(.{' + str(length) + r'})\1{' + str(max_repeat) + r',}'

        def replace_func(match):
            unit = match.group(1)
            # 保留 max_repeat 次重复 + "..."
            return unit * max_repeat + '...[重复内容已截断]'

        text = re.sub(pattern, replace_func, text)

    return text


def suggest_transcribe_fix(quality_result: Dict) -> Optional[str]:
    """
    根据质量检测结果，建议修复方案

    Args:
        quality_result: check_text_quality 返回的结果

    Returns:
        修复建议（字符串）或 None
    """
    if quality_result['is_valid']:
        return None

    if quality_result['has_hallucination']:
        return (
            "建议使用更大的 Whisper 模型（如 small/medium/large）重新转录，"
            "或检查音频质量（降噪、音量增强）"
        )

    if quality_result['reason'] == '文本为空':
        return "可能是纯音乐或无人声内容，建议手动确认"

    if '文本过短' in quality_result.get('reason', ''):
        return "转录结果过短，可能音频时长过短或转录失败"

    return "未知问题，建议手动检查音频和转录结果"
